import { Color } from "@/utils/CanvasUtils/CanvasType";
import Mota, { MotaInterface } from "@/mota";
import { ImageName } from "@/mota/data/ImageLoader";

export type FontWeight = 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | "lighter" | "bold" | "bolder" | "normal";

/**
 * 提升消息
 * [0:内容,1:字宽,2:字大小,3:前景色,4:左右对齐,5:背景色,6:图标,7:显示时长,8:透明度,9:高度率];
 *
 * 经历显示时长的显示后，慢慢减少透明度，完全透明后减少高度，高度为零则删除此消息
 */
export type TipMessage = [string, FontWeight, number, Color, AlignSetting | undefined, Color | undefined, ImageName | undefined, number, number, number];

export default class TipUtils implements MotaInterface {
	public readonly Mota: Mota;

	public list: Set<TipMessage> = new Set();

	public transparencySpeed: number = 0.1;

	public heightSpeed: number = 0.1;

	public constructor(mota: Mota) {
		this.Mota = mota;
	}
	public ZIndex: number = 7;

	public get tipList() {
		return Array.from(this.list);
	}

	public Add(content: string, weight: FontWeight, size: number, color: Color, align: AlignSetting | undefined, back: Color | undefined, image: ImageName | undefined, time: number): TipMessage {
		const message: TipMessage = [content, weight, size, color, align, back, image, time, 1, 1];
		this.list.add(message);
		return message;
	}

	public AddMessage(message: string) {
		this.Add(message, 400, 1 / 2, "#959595", "left", "#00000099", undefined, 150);
	}

	public AddFloor(name: string) {
		this.Add(name, 800, 1 / 1.7, "#959595", "center", "#00000099", undefined, 150);
	}

	public AddIconMessage(icon: ImageName, message: string) {
		this.Add(message, 400, 1 / 2, "#959595", "left", "#00000099", icon, 150);
	}

	public AddSay(image: ImageName, message: string) {
		this.Add(`：${message}`, 400, 1 / 2, "#959595", "left", "#00000099", image, 150);
	}

	public Delete(tip: TipMessage): void {
		this.list.delete(tip);
	}

	public Draw: MotaInterface["Draw"] = (draw) => {
		const { _2d } = draw;

		_2d.save();

		draw.translate(4, 0);

		for (const tip of this.tipList) {
			const [content, weight, size, color, align, back, image, , transparency, heightI] = tip;
			const padding = 0.125;
			const padding2 = padding * 2;
			const hasImage = image !== undefined;
			const height = (size + padding2) * heightI;
			_2d.save();
			_2d.globalAlpha = transparency;
			draw.SetFont(weight, size, "Mota");
			if (back) {
				let width = draw.measureText(content) + padding2;
				if (hasImage) { width += size + padding2; }
				let x = 0;
				if (align === "center") { x = (11 - width) / 2; }
				else if (align === "right" || align === "end") { x = 11 - width; }
				_2d.fillStyle = back;
				draw.fillRect(x, 0, width, height);
			}
			{
				_2d.fillStyle = color;
				_2d.textBaseline = "middle";
				let x = padding;
				if (hasImage) { x += size + padding2; }
				if (align === "center") { _2d.textAlign = "center"; x = 5.5; }
				else if (align === "right" || align === "end") { _2d.textAlign = "right"; x = 11 - padding; }
				if (image !== undefined) {
					draw.DrawImage(image, true, 0, [x - size - padding, padding, size, size]);
				}
				draw.fillText(content, x, height / 2);
			}
			_2d.restore();
			draw.translate(0, height);
		}

		_2d.restore();
	}

	public Trigger(): void {
		const { tipList, Mota: { speedUtils }, transparencySpeed, heightSpeed } = this;
		for (const tip of tipList) {
			const [, , , , , , , time, transparency, heightI] = tip;
			if (time > 0) {
				tip[7] -= speedUtils.speed2.Value;
			} else if (transparency > 0) {
				tip[8] -= transparencySpeed;
				if (tip[8] < 0) {
					tip[8] = 0;
				}
			} else if (heightI > 0) {
				tip[9] -= heightSpeed;
				if (tip[9] < 0) {
					tip[9] = 0;
				}
			} else {
				this.Delete(tip);
			}
		}
	}
}
